#include<iostream>
#include<string>
#include<mysql/mysql.h>

#define HOST "127.0.0.1"
#define USER "root"
#define PASS "2794721791pfg."
#define PORT 3306
#define DBNAME "gobang"
int main()
{
    // 1.初始化MYSQL句柄
    // MYSQL *mysql_init(MYSQL *mysql)
    // mysql为空则动态申请句柄空间进⾏初始化
    // 成功返回句柄指针， 失败返回NULL
    MYSQL* mysql=mysql_init(nullptr);
    if(mysql==NULL)
    {
        std::cout<<"mysql_init failed"<<std::endl;
        return -1;
    }

    // 2.连接服务器
    // MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user,const char *passwd
    //                          ,const char *db, unsigned int port,const char *unix_socket, unsigned long client_flag);
    // mysql--初始化完成的句柄
    // host---连接的mysql服务器的地址
    // user---连接的服务器的⽤⼾名
    // passwd-连接的服务器的密码
    // db ----默认选择的数据库名称
    // port---连接的服务器的端⼝： 默认0是3306端⼝
    // unix_socket---通信管道⽂件或者socket⽂件，通常置NULL
    // client_flag---客⼾端标志位，通常置0
    // 成功返回句柄指针，失败返回NULL
    if(mysql_real_connect(mysql,HOST,USER,PASS,DBNAME,PORT,nullptr,0)==NULL)
    {
        std::cout<<"mysql_real_connect failed:"<<mysql_error(mysql)<<std::endl;
        mysql_close(mysql);
        return -1;
    }

    // 3.设置字符集
    // int mysql_set_character_set(MYSQL *mysql, const char *csname)
    // mysql--初始化完成的句柄
    // csname--字符集名称，通常："utf8"
    // 成功返回0， 失败返回⾮0
    if(mysql_set_character_set(mysql,"utf8")!=0)
    {
        std::cout<<"mysql_set_character_set failed:"<<mysql_error(mysql)<<std::endl;
        mysql_close(mysql);
        return -1;
    }

    // 4.选择数据库
    // int mysql_select_db(MYSQL *mysql, const char *db)
    // mysql--初始化完成的句柄
    // db-----要切换选择的数据库名称
    // 成功返回0， 失败返回⾮0

    // 5.执行sql语句
    // int mysql_query(MYSQL *mysql, const char *stmt_str)
    // mysql--初始化完成的句柄
    // stmt_str--要执⾏的sql语句
    // 成功返回0， 失败返回⾮0

    //5.1插入数据
    //const char* sql="insert stu values(null,18,'张三',66,77,88);";
    //5.2修改数据
    //const char* sql="update stu set chinese=chinese+20 where name='张三';";
    //5.3删除数据
    //const char* sql="delete from stu where id=1;";
    //5.4查询数据
    const char* sql="select * from stu;";
    int ret=mysql_query(mysql,sql);
    if(ret!=0)
    {
        std::cout<<sql<<std::endl;
        std::cout<<"mysql_query failed:"<<mysql_error(mysql)<<std::endl;
        mysql_close(mysql);
        return -1;
    }

    //6.查询语句的执行结果需要保存到本地
    // MYSQL_RES *mysql_store_result(MYSQL *mysql)
    // mysql--初始化完成的句柄
    // 成功返回结果集的指针， 失败返回NULL
    MYSQL_RES* res=mysql_store_result(mysql);
    if(res==NULL)
    {
        mysql_close(mysql);
        return -1;
    }

    //7.获取查询结果集中的结果条数
    // uint64_t mysql_num_rows(MYSQL_RES *result)；
    // result--保存到本地的结果集地址
    // 返回查询结果集中数据的条数
    uint64_t num_row=mysql_num_rows(res);
    //8.获取查询结果集中的列数
    // unsigned int mysql_num_fields(MYSQL_RES *result)
    // result--保存到本地的结果集地址
    // 返回查询结果集中每⼀条数据的列数
    unsigned int num_col=mysql_num_fields(res);

    //9.遍历保存在本地的查询结果集
    for(int i=0;i<num_row;i++)
    {
        //取出一行数据
        // MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
        // result--保存到本地的结果集地址
        // 返回值实际上是⼀个char **的指针，将每⼀条数据做成了字符串指针数组
        // row[0]-第0列 row[1]-第1列 ......
        MYSQL_ROW row=mysql_fetch_row(res);
        for(int j=0;j<num_col;j++)
        {
            std::cout<<row[j]<<"\t";
        }
        std::cout<<std::endl;
    }
    //10.释放结果集
    mysql_free_result(res);

    //11.关闭连接释放句柄
    mysql_close(mysql);
    return 0;
}